using CodePlex.DnD4eCampaignManager.CampaignManagerTests.TestUtilities;
using CodePlex.DnD4eCampaignManager.DnD4e;
using CodePlex.DnD4eCampaignManager.DnD4e.Enums;
using CodePlex.DnD4eCampaignManager.DnD4e.Interfaces;
using NUnit.Framework;
using Rhino.Mocks;
using StructureMap.AutoMocking;

namespace CodePlex.DnD4eCampaignManager.CampaignManagerTests.DnD4eTests
{
    [TestFixture]
    public class PlayerCharacterTests
    {
        private const int AGE = 25;
        private const Alignment ALIGNMENT = Alignment.Good;
        private const string CLASS_NAME = "Fighter";
        private const string CONDITIONS = "5 Ongoing Fire Damage (Save Ends)";
        private const string EPIC_DESTINY = "Epic Something";
        private const int EXPERIENCE_POINTS = 2000;
        private const string HEIGHT = "5\"11'";
        private const string NAME = "D. Bag";
        private const string PARAGON_PATH = "Specialized Something";
        private const string RACE = "Human";
        private const string SPECIAL_QUALITIES = "Resist Cold 5";
        private const string TACTICS = "Action Points = 1";
        private const int WEIGHT = 220;
        private RhinoAutoMocker<PlayerCharacter> _playerCharacterMocker;

        [Test]
        public void AbilitiesComponentHandlesAbilityCharisma()
        {
            const int charisma = 15;
            _playerCharacterMocker.Get<IAbilities>().Expect(x => x.AbilityCharisma).Return(charisma);
            _playerCharacterMocker.Get<IAbilities>().Expect(x => x.AbilityCharisma = charisma);
            _playerCharacterMocker.ClassUnderTest.AbilityCharisma = _playerCharacterMocker.ClassUnderTest.AbilityCharisma;
        }

        [Test]
        public void AbilitiesComponentHandlesAbilityConstitution()
        {
            const int constitution = 15;
            _playerCharacterMocker.Get<IAbilities>().Expect(x => x.AbilityConstitution).Return(constitution);
            _playerCharacterMocker.Get<IAbilities>().Expect(x => x.AbilityConstitution = constitution);
            _playerCharacterMocker.ClassUnderTest.AbilityConstitution = _playerCharacterMocker.ClassUnderTest.AbilityConstitution;
        }

        [Test]
        public void AbilitiesComponentHandlesAbilityDexterity()
        {
            const int dexterity = 15;
            _playerCharacterMocker.Get<IAbilities>().Expect(x => x.AbilityDexterity).Return(dexterity);
            _playerCharacterMocker.Get<IAbilities>().Expect(x => x.AbilityDexterity = dexterity);
            _playerCharacterMocker.ClassUnderTest.AbilityDexterity = _playerCharacterMocker.ClassUnderTest.AbilityDexterity;
        }

        [Test]
        public void AbilitiesComponentHandlesAbilityIntelligence()
        {
            const int intelligence = 15;
            _playerCharacterMocker.Get<IAbilities>().Expect(x => x.AbilityIntelligence).Return(intelligence);
            _playerCharacterMocker.Get<IAbilities>().Expect(x => x.AbilityIntelligence = intelligence);
            _playerCharacterMocker.ClassUnderTest.AbilityIntelligence = _playerCharacterMocker.ClassUnderTest.AbilityIntelligence;
        }

        [Test]
        public void AbilitiesComponentHandlesAbilityStrength()
        {
            const int strength = 15;
            _playerCharacterMocker.Get<IAbilities>().Expect(x => x.AbilityStrength).Return(strength);
            _playerCharacterMocker.Get<IAbilities>().Expect(x => x.AbilityStrength = strength);
            _playerCharacterMocker.ClassUnderTest.AbilityStrength = _playerCharacterMocker.ClassUnderTest.AbilityStrength;
        }

        [Test]
        public void AbilitiesComponentHandlesAbilityWisdom()
        {
            const int wisdom = 15;
            _playerCharacterMocker.Get<IAbilities>().Expect(x => x.AbilityWisdom).Return(wisdom);
            _playerCharacterMocker.Get<IAbilities>().Expect(x => x.AbilityWisdom = wisdom);
            _playerCharacterMocker.ClassUnderTest.AbilityWisdom = _playerCharacterMocker.ClassUnderTest.AbilityWisdom;
        }

        [Test]
        public void CombatantIsFormatedProperlyForDisplay()
        {
            IPlayerCharacter playerCharacter1 = DefaultTestObjects.TestPlayerCharacter();
            IPlayerCharacter playerCharacter2 = DefaultTestObjects.TestPlayerCharacter();
            playerCharacter2.HitPointsTemporary = 11;
            playerCharacter2.MovementSpeedOther = "Climb 4";
            Assert.AreEqual("Conan - 31 (2 temp)/60; AC: 15, Fort: 14, Ref: 17, Will: 20; Surges: 3/5; Speed: 6",
                            playerCharacter1.FormatCombatantForDisplay());
            Assert.AreEqual("Conan - 40 (11 temp)/60; AC: 15, Fort: 14, Ref: 17, Will: 20; Surges: 3/5; Speed: 6, Climb 4",
                            playerCharacter2.FormatCombatantForDisplay());
        }

        [Test]
        public void DefensesComponentHandlesDefenseArmorClass()
        {
            const int armorClass = 12;
            _playerCharacterMocker.Get<IDefenses>().Expect(x => x.DefenseArmorClass = armorClass);
            _playerCharacterMocker.Get<IDefenses>().Expect(x => x.DefenseArmorClass).Return(armorClass);
            _playerCharacterMocker.ClassUnderTest.DefenseArmorClass = _playerCharacterMocker.ClassUnderTest.DefenseArmorClass;
        }

        [Test]
        public void DefensesComponentHandlesDefenseFortitude()
        {
            const int fortitudeDefense = 12;
            _playerCharacterMocker.Get<IDefenses>().Expect(x => x.DefenseFortitude = fortitudeDefense);
            _playerCharacterMocker.Get<IDefenses>().Expect(x => x.DefenseFortitude).Return(fortitudeDefense);
            _playerCharacterMocker.ClassUnderTest.DefenseFortitude = _playerCharacterMocker.ClassUnderTest.DefenseFortitude;
        }

        [Test]
        public void DefensesComponentHandlesDefenseReflex()
        {
            const int reflexDefense = 12;
            _playerCharacterMocker.Get<IDefenses>().Expect(x => x.DefenseReflex = reflexDefense);
            _playerCharacterMocker.Get<IDefenses>().Expect(x => x.DefenseReflex).Return(reflexDefense);
            _playerCharacterMocker.ClassUnderTest.DefenseReflex = _playerCharacterMocker.ClassUnderTest.DefenseReflex;
        }

        [Test]
        public void DefensesComponentHandlesDefenseWillpower()
        {
            const int willpowerDefense = 12;
            _playerCharacterMocker.Get<IDefenses>().Expect(x => x.DefenseWillpower = willpowerDefense);
            _playerCharacterMocker.Get<IDefenses>().Expect(x => x.DefenseWillpower).Return(willpowerDefense);
            _playerCharacterMocker.ClassUnderTest.DefenseWillpower = _playerCharacterMocker.ClassUnderTest.DefenseWillpower;
        }

        [Test]
        public void HasAge()
        {
            _playerCharacterMocker.ClassUnderTest.CharacterAge = AGE;
            Assert.AreEqual(AGE, _playerCharacterMocker.ClassUnderTest.CharacterAge);
        }

        [Test]
        public void HasAlignment()
        {
            _playerCharacterMocker.ClassUnderTest.CharacterAlignment = ALIGNMENT;
            Assert.AreEqual(ALIGNMENT, _playerCharacterMocker.ClassUnderTest.CharacterAlignment);
        }

        [Test]
        public void HasClass()
        {
            _playerCharacterMocker.ClassUnderTest.CharacterClass = CLASS_NAME;
            Assert.AreEqual(CLASS_NAME, _playerCharacterMocker.ClassUnderTest.CharacterClass);
        }

        [Test]
        public void HasConditions()
        {
            _playerCharacterMocker.ClassUnderTest.Conditions = CONDITIONS;
            Assert.AreEqual(CONDITIONS, _playerCharacterMocker.ClassUnderTest.Conditions);
        }

        [Test]
        public void HasCorrectLevelBasedOnXP()
        {
            _playerCharacterMocker.ClassUnderTest.CharacterExperiencePoints = 999;
            Assert.AreEqual(1, _playerCharacterMocker.ClassUnderTest.CharacterLevel);
            _playerCharacterMocker.ClassUnderTest.CharacterExperiencePoints = 1000;
            Assert.AreEqual(2, _playerCharacterMocker.ClassUnderTest.CharacterLevel);
            _playerCharacterMocker.ClassUnderTest.CharacterExperiencePoints = 1001;
            Assert.AreEqual(2, _playerCharacterMocker.ClassUnderTest.CharacterLevel);
            _playerCharacterMocker.ClassUnderTest.CharacterExperiencePoints = 2249;
            Assert.AreEqual(2, _playerCharacterMocker.ClassUnderTest.CharacterLevel);
            _playerCharacterMocker.ClassUnderTest.CharacterExperiencePoints = 2250;
            Assert.AreEqual(3, _playerCharacterMocker.ClassUnderTest.CharacterLevel);
        }

        [Test]
        public void HasEpicDestiny()
        {
            _playerCharacterMocker.ClassUnderTest.CharacterEpicDestiny = EPIC_DESTINY;
            Assert.AreEqual(EPIC_DESTINY, _playerCharacterMocker.ClassUnderTest.CharacterEpicDestiny);
        }

        [Test]
        public void HasExperiencePoints()
        {
            _playerCharacterMocker.ClassUnderTest.CharacterExperiencePoints = EXPERIENCE_POINTS;
            Assert.AreEqual(EXPERIENCE_POINTS, _playerCharacterMocker.ClassUnderTest.CharacterExperiencePoints);
        }

        [Test]
        public void HasGender()
        {
            _playerCharacterMocker.ClassUnderTest.CharacterGender = Gender.Male;
            Assert.AreEqual(Gender.Male, _playerCharacterMocker.ClassUnderTest.CharacterGender);
        }

        [Test]
        public void HasHeight()
        {
            _playerCharacterMocker.ClassUnderTest.CharacterHeight = HEIGHT;
            Assert.AreEqual(HEIGHT, _playerCharacterMocker.ClassUnderTest.CharacterHeight);
        }

        [Test]
        public void HasName()
        {
            _playerCharacterMocker.ClassUnderTest.Name = NAME;
            Assert.AreEqual(NAME, _playerCharacterMocker.ClassUnderTest.Name);
        }

        [Test]
        public void HasParagonPath()
        {
            _playerCharacterMocker.ClassUnderTest.CharacterParagonPath = PARAGON_PATH;
            Assert.AreEqual(PARAGON_PATH, _playerCharacterMocker.ClassUnderTest.CharacterParagonPath);
        }

        [Test]
        public void HasRace()
        {
            _playerCharacterMocker.ClassUnderTest.CharacterRace = RACE;
            Assert.AreEqual(RACE, _playerCharacterMocker.ClassUnderTest.CharacterRace);
        }

        [Test]
        public void HasSpecialQualities()
        {
            _playerCharacterMocker.ClassUnderTest.SpecialQualities = SPECIAL_QUALITIES;
            Assert.AreEqual(SPECIAL_QUALITIES, _playerCharacterMocker.ClassUnderTest.SpecialQualities);
        }

        [Test]
        public void HasTactics()
        {
            _playerCharacterMocker.ClassUnderTest.Tactics = TACTICS;
            Assert.AreEqual(TACTICS, _playerCharacterMocker.ClassUnderTest.Tactics);
        }

        [Test]
        public void HasWeight()
        {
            _playerCharacterMocker.ClassUnderTest.CharacterWeight = WEIGHT;
            Assert.AreEqual(WEIGHT, _playerCharacterMocker.ClassUnderTest.CharacterWeight);
        }

        [Test]
        public void HealingSurgesComponentHandlesDamage()
        {
            const int hitPointsLost = 5;
            _playerCharacterMocker.Get<IHealingSurges>().Expect(x => x.Damage(hitPointsLost));
            _playerCharacterMocker.ClassUnderTest.Damage(hitPointsLost);
        }

        [Test]
        public void HealingSurgesComponentHandlesHealing()
        {
            const int hitPointsRecovered = 5;
            _playerCharacterMocker.Get<IHealingSurges>().Expect(x => x.Heal(hitPointsRecovered));
            _playerCharacterMocker.ClassUnderTest.Heal(hitPointsRecovered);
        }

        [Test]
        public void HealingSurgesComponentHandlesFailedDeathSaves()
        {
            const int failedDeathSaves = 2;
            _playerCharacterMocker.Get<IHealingSurges>().Expect(x => x.FailedDeathSaves = failedDeathSaves);
            _playerCharacterMocker.Get<IHealingSurges>().Expect(x => x.FailedDeathSaves).Return(failedDeathSaves);
            _playerCharacterMocker.ClassUnderTest.FailedDeathSaves = _playerCharacterMocker.ClassUnderTest.FailedDeathSaves;
        }

        [Test]
        public void HealingSurgesComponentHandlesHitPointsBloodied()
        {
            const int hitPointsBloodied = 5;
            _playerCharacterMocker.Get<IHealingSurges>().Expect(x => x.HitPointsBloodied).Return(hitPointsBloodied);
            Assert.AreEqual(hitPointsBloodied, _playerCharacterMocker.ClassUnderTest.HitPointsBloodied);
        }

        [Test]
        public void HealingSurgesComponentHandlesHitPointsCurrent()
        {
            const int hitPointsCurrent = 5;
            _playerCharacterMocker.Get<IHealingSurges>().Expect(x => x.HitPointsCurrent = hitPointsCurrent);
            _playerCharacterMocker.Get<IHealingSurges>().Expect(x => x.HitPointsCurrent).Return(hitPointsCurrent);
            _playerCharacterMocker.ClassUnderTest.HitPointsCurrent = _playerCharacterMocker.ClassUnderTest.HitPointsCurrent;
        }

        [Test]
        public void HealingSurgesComponentHandlesHitPointsMaximim()
        {
            const int hitPointsMaximum = 5;
            _playerCharacterMocker.Get<IHealingSurges>().Expect(x => x.HitPointsMaximum = hitPointsMaximum);
            _playerCharacterMocker.Get<IHealingSurges>().Expect(x => x.HitPointsMaximum).Return(hitPointsMaximum);
            _playerCharacterMocker.ClassUnderTest.HitPointsMaximum = _playerCharacterMocker.ClassUnderTest.HitPointsMaximum;
        }

        [Test]
        public void HealingSurgesComponentHandlesHitPointsTemporary()
        {
            const int hitPointsTemporary = 5;
            _playerCharacterMocker.Get<IHealingSurges>().Expect(x => x.HitPointsTemporary = hitPointsTemporary);
            _playerCharacterMocker.Get<IHealingSurges>().Expect(x => x.HitPointsTemporary).Return(hitPointsTemporary);
            _playerCharacterMocker.ClassUnderTest.HitPointsTemporary = _playerCharacterMocker.ClassUnderTest.HitPointsTemporary;
        }

        [Test]
        public void HealingSurgesComponentHandlesIsBloodied()
        {
            _playerCharacterMocker.Get<IHealingSurges>().Expect(x => x.IsBloodied).Return(true);
            Assert.IsTrue(_playerCharacterMocker.ClassUnderTest.IsBloodied);
        }

        [Test]
        public void ImplementsIAbilities()
        {
            Assert.IsInstanceOfType(typeof ( IAbilities ), _playerCharacterMocker.ClassUnderTest);
        }

        [Test]
        public void ImplementsICombatant()
        {
            Assert.IsInstanceOfType(typeof ( ICombatant ), _playerCharacterMocker.ClassUnderTest);
        }

        [Test]
        public void ImplementsIDefenses()
        {
            Assert.IsInstanceOfType(typeof ( IDefenses ), _playerCharacterMocker.ClassUnderTest);
        }

        [Test]
        public void ImplementsIHealingSurges()
        {
            Assert.IsInstanceOfType(typeof ( IHealingSurges ), _playerCharacterMocker.ClassUnderTest);
        }

        [Test]
        public void ImplementsIHitPoints()
        {
            Assert.IsInstanceOfType(typeof ( IHitPoints ), _playerCharacterMocker.ClassUnderTest);
        }

        [Test]
        public void ImplementsIMovement()
        {
            Assert.IsInstanceOfType(typeof ( IMovement ), _playerCharacterMocker.ClassUnderTest);
        }

        [Test]
        public void ImplementsIPlayerCharacter()
        {
            Assert.IsInstanceOfType(typeof ( IPlayerCharacter ), _playerCharacterMocker.ClassUnderTest);
        }

        [Test]
        public void ImplementsIPowers()
        {
            Assert.IsInstanceOfType(typeof ( IPowers ), _playerCharacterMocker.ClassUnderTest);
        }

        [Test]
        public void ImplementsISenses()
        {
            Assert.IsInstanceOfType(typeof ( ISenses ), _playerCharacterMocker.ClassUnderTest);
        }

        [Test]
        public void InitiativeComponentHandlesIniativeScore()
        {
            const int initiativeScore = 5;
            _playerCharacterMocker.Get<IInitiative>().Expect(x => x.InitiativeScore).Return(initiativeScore);
            _playerCharacterMocker.Get<IInitiative>().Expect(x => x.InitiativeScore = initiativeScore);
            _playerCharacterMocker.ClassUnderTest.InitiativeScore = _playerCharacterMocker.ClassUnderTest.InitiativeScore;
        }

        [Test]
        public void InitiativeComponentHandlesInitiativeModifier()
        {
            const int initiativeModifier = 6;
            _playerCharacterMocker.Get<IInitiative>().Expect(x => x.InitiativeModifier).Return(initiativeModifier);
            _playerCharacterMocker.Get<IInitiative>().Expect(x => x.InitiativeModifier = initiativeModifier);
            _playerCharacterMocker.ClassUnderTest.InitiativeModifier = _playerCharacterMocker.ClassUnderTest.InitiativeModifier;
        }

        [Test]
        public void InitiativeComponentHandlesInitiativeRoll()
        {
            const int initiativeRoll = 7;
            _playerCharacterMocker.Get<IInitiative>().Expect(x => x.InitiativeRoll).Return(initiativeRoll);
            _playerCharacterMocker.Get<IInitiative>().Expect(x => x.InitiativeRoll = initiativeRoll);
            _playerCharacterMocker.ClassUnderTest.InitiativeRoll = _playerCharacterMocker.ClassUnderTest.InitiativeRoll;
        }

        [Test]
        public void MovementComponentHandlesMovementSpeed()
        {
            const int alternateMovementModes = 8;
            _playerCharacterMocker.Get<IMovement>().Expect(x => x.MovementSpeed = alternateMovementModes);
            _playerCharacterMocker.Get<IMovement>().Expect(x => x.MovementSpeed).Return(alternateMovementModes);
            _playerCharacterMocker.ClassUnderTest.MovementSpeed = _playerCharacterMocker.ClassUnderTest.MovementSpeed;
        }

        [Test]
        public void MovementComponentHandlesMovementSpeedOther()
        {
            const string alternateMovementModes = "Swim 10";
            _playerCharacterMocker.Get<IMovement>().Expect(x => x.MovementSpeedOther = alternateMovementModes);
            _playerCharacterMocker.Get<IMovement>().Expect(x => x.MovementSpeedOther).Return(alternateMovementModes);
            _playerCharacterMocker.ClassUnderTest.MovementSpeedOther = _playerCharacterMocker.ClassUnderTest.MovementSpeedOther;
        }

        [Test]
        public void MovementComponentHandlesMovementStealth()
        {
            const int movementStealth = 8;
            _playerCharacterMocker.Get<IMovement>().Expect(x => x.MovementStealth = movementStealth);
            _playerCharacterMocker.Get<IMovement>().Expect(x => x.MovementStealth).Return(movementStealth);
            _playerCharacterMocker.ClassUnderTest.MovementStealth = _playerCharacterMocker.ClassUnderTest.MovementStealth;
        }

        [Test]
        public void PowersComponentHandlesPowersAtWill()
        {
            const string powersAtWill = "Hits you with a sword";
            _playerCharacterMocker.Get<IPowers>().Expect(x => x.PowersAtWill = powersAtWill);
            _playerCharacterMocker.Get<IPowers>().Expect(x => x.PowersAtWill).Return(powersAtWill);
            _playerCharacterMocker.ClassUnderTest.PowersAtWill = _playerCharacterMocker.ClassUnderTest.PowersAtWill;
        }

        [Test]
        public void PowersComponentHandlesPowersDaily()
        {
            const string powersDaily = "Hits you with a sword";
            _playerCharacterMocker.Get<IPowers>().Expect(x => x.PowersDaily = powersDaily);
            _playerCharacterMocker.Get<IPowers>().Expect(x => x.PowersDaily).Return(powersDaily);
            _playerCharacterMocker.ClassUnderTest.PowersDaily = _playerCharacterMocker.ClassUnderTest.PowersDaily;
        }

        [Test]
        public void PowersComponentHandlesPowersEncounter()
        {
            const string powersEncounter = "Hits you with a sword";
            _playerCharacterMocker.Get<IPowers>().Expect(x => x.PowersEncounter = powersEncounter);
            _playerCharacterMocker.Get<IPowers>().Expect(x => x.PowersEncounter).Return(powersEncounter);
            _playerCharacterMocker.ClassUnderTest.PowersEncounter = _playerCharacterMocker.ClassUnderTest.PowersEncounter;
        }

        [Test]
        public void SensesComponentHandlesInsight()
        {
            const int insight = 12;
            _playerCharacterMocker.Get<ISenses>().Expect(x => x.SensesInsight = insight);
            _playerCharacterMocker.Get<ISenses>().Expect(x => x.SensesInsight).Return(insight);
            _playerCharacterMocker.ClassUnderTest.SensesInsight = _playerCharacterMocker.ClassUnderTest.SensesInsight;
        }

        [Test]
        public void SensesComponentHandlesInsightPassive()
        {
            const int insightPassive = 12;
            _playerCharacterMocker.Get<ISenses>().Expect(x => x.SensesInsightPassive = insightPassive);
            _playerCharacterMocker.Get<ISenses>().Expect(x => x.SensesInsightPassive).Return(insightPassive);
            _playerCharacterMocker.ClassUnderTest.SensesInsightPassive = _playerCharacterMocker.ClassUnderTest.SensesInsightPassive;
        }

        [Test]
        public void SensesComponentHandlesPerception()
        {
            const int perception = 12;
            _playerCharacterMocker.Get<ISenses>().Expect(x => x.SensesPerception = perception);
            _playerCharacterMocker.Get<ISenses>().Expect(x => x.SensesPerception).Return(perception);
            _playerCharacterMocker.ClassUnderTest.SensesPerception = _playerCharacterMocker.ClassUnderTest.SensesPerception;
        }

        [Test]
        public void SensesComponentHandlesPerceptionPassive()
        {
            const int perceptionPassive = 12;
            _playerCharacterMocker.Get<ISenses>().Expect(x => x.SensesPerceptionPassive = perceptionPassive);
            _playerCharacterMocker.Get<ISenses>().Expect(x => x.SensesPerceptionPassive).Return(perceptionPassive);
            _playerCharacterMocker.ClassUnderTest.SensesPerceptionPassive = _playerCharacterMocker.ClassUnderTest.SensesPerceptionPassive;
        }

        [Test]
        public void SensesComponentHandlesSensesOther()
        {
            const string sensesOther = "dark vision";
            _playerCharacterMocker.Get<ISenses>().Expect(x => x.SensesOther = sensesOther);
            _playerCharacterMocker.Get<ISenses>().Expect(x => x.SensesOther).Return(sensesOther);
            _playerCharacterMocker.ClassUnderTest.SensesOther = _playerCharacterMocker.ClassUnderTest.SensesOther;
        }

        [SetUp]
        public void SetUp()
        {
            _playerCharacterMocker = new RhinoAutoMocker<PlayerCharacter>();
        }

        [TearDown]
        public void TearDown()
        {
            _playerCharacterMocker.Get<IInitiative>().VerifyAllExpectations();
            _playerCharacterMocker.Get<IAbilities>().VerifyAllExpectations();
            _playerCharacterMocker.Get<IHealingSurges>().VerifyAllExpectations();
            _playerCharacterMocker.Get<IHitPoints>().VerifyAllExpectations();
            _playerCharacterMocker.Get<ISenses>().VerifyAllExpectations();
            _playerCharacterMocker.Get<IMovement>().VerifyAllExpectations();
            _playerCharacterMocker.Get<IDefenses>().VerifyAllExpectations();
        }
    }
}